package com.quectel.cms.controller.propertybill;


import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.propertybill.PropertyBillBusiness;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.cms.vo.home.PropertyBillBuildingRoomCountVo;
import com.quectel.cms.vo.home.PropertyBillRoomCountVo;
import com.quectel.cms.vo.propertybill.PropertyBillFloorRoomCountVo;
import com.quectel.cms.vo.propertybill.PropertyBillInfoVo;
import com.quectel.cms.vo.propertybill.PropertyBillItemInfoVo;
import com.quectel.constant.core.propertybill.PropertyBillConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.household.service.HouseholdRoomService;
import com.quectel.core.module.propertybill.dto.PropertyBillDto;
import com.quectel.core.module.propertybill.service.*;
import com.quectel.core.module.propertybill.vo.PropertyBillAmountVo;
import com.quectel.core.module.propertybill.vo.PropertyChargeableItemAmountVo;
import com.quectel.core.module.village.dto.VillageBuildingDto;
import com.quectel.core.module.village.dto.VillageFloorDto;
import com.quectel.core.module.village.dto.VillageRoomDto;
import com.quectel.core.module.village.service.VillageBuildingService;
import com.quectel.core.module.village.service.VillageFloorService;
import com.quectel.core.module.village.service.VillageRoomService;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/03/31 16:28
 */
@RestController
@RequestMapping("propertyFeeStatistics")
@Tag(name = "PropertyFeeStatisticsController", description = "物业收费统计相关api")
public class PropertyFeeStatisticsController extends BaseController {

    @DubboReference
    private PropertyBillService propertyBillService;
    @DubboReference
    private VillageBuildingService villageBuildingService;
    @DubboReference
    private VillageRoomService villageRoomService;
    @DubboReference
    private VillageFloorService villageFloorService;
    @DubboReference
    private PropertyChargeableListService propertyChargeableListService;
    @DubboReference
    private PropertyChargeableListItemBindingService propertyChargeableListItemBindingService;
    @DubboReference
    private PropertyChargeableListDueDateService propertyChargeableListDueDateService;
    @DubboReference
    private HouseholdRoomService householdRoomService;

    @DubboReference
    private PropertyChargeableItemService propertyChargeableItemService;
    @Autowired
    private PropertyBillActivityService propertyBillActivityService;

    @Autowired
    private PropertyBillBusiness propertyBillBusiness;


    /**
     * 根据楼栋筛选楼层
     */
    @GetMapping("queryByBuildingId")
    @Operation(summary = "根据楼栋筛选楼层,查询逾期账单对应楼层")
    public Response<List<VillageFloorDto>> queryByBuildingId(
            @Parameter(description = "楼栋") @RequestParam Long buildingId
    ) {
        //查询列表数据
        Request request = Request.configParamsNotPage(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        request.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        request.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        request.put(LambdaUtil.getFieldName(PropertyBillDto::getBuildingId), buildingId);
        request.put(LambdaUtil.getFieldName(PropertyBillDto::getOverdueStatus), SystemConstants.NORMAL);

        List<VillageFloorDto> list = new ArrayList<>();
        List<Long> longs = propertyBillService.queryFloorIds(request.getParams());
        if (CollectionUtils.isNotEmpty(longs)) {
            for (Long aLong : longs) {
                VillageFloorDto villageFloorDto = villageFloorService.selectCacheById(aLong);
                if (villageFloorDto != null) {
                    list.add(villageFloorDto);
                }
            }
        }

        return Response.<List<VillageFloorDto>>ok().wrap(list);
    }


    /**
     * 物业费统计
     */
    @GetMapping("propertyBillRoomCount")
    @Operation(summary = "物业收费房间收费统计")
    public Response<PropertyBillRoomCountVo> propertyBillRoomCount(
            @Parameter(description = "小区id") @RequestParam(required = false) Long villageId
    ) {
        PropertyBillRoomCountVo propertyBillRoomCountVo = new PropertyBillRoomCountVo();

        //查询所有的房间 计数
        Map<String, Object> params = new HashMap<>();
        params.put(LambdaUtil.getFieldName(VillageRoomDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        params.put(LambdaUtil.getFieldName(VillageRoomDto::getVillageId), villageId);
        propertyBillRoomCountVo.setTotalCount(villageRoomService.queryTotal(params));

        Map<String, Object> overdueParams = new HashMap<>();

        overdueParams.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        overdueParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        overdueParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        overdueParams.put(LambdaUtil.getFieldName(PropertyBillDto::getOverdueStatus), SystemConstants.NORMAL);
        propertyBillRoomCountVo.setOverdueCount(propertyBillService.countRoom(overdueParams));

        return Response.<PropertyBillRoomCountVo>ok().wrap(propertyBillRoomCountVo);
    }

    /**
     * 楼栋物业收费统计
     */
    @GetMapping("propertyBillBuildingRoomCount")
    @Operation(summary = "楼栋物业收费统计")
    public Response<Page<PropertyBillBuildingRoomCountVo>> propertyBillBuildingRoomCount(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "小区id") @RequestParam(required = false) Long villageId,
            @Parameter(description = "收费标准id") @RequestParam(required = false) Long chargeableListId,
            @Parameter(description = "收费周期") @RequestParam(required = false) Byte periodType,
            @Parameter(description = "年份") @RequestParam(required = false) Integer year,
            @Parameter(description = "时间段对应的值,如1月对应的是1") @RequestParam(required = false) Integer periodValue
    ) {

        //查询列表数据
        Request request = Request.configParamsNotPage(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        Map<String, Object> params = new HashMap<>();
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getChargeableListId), chargeableListId);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getYear), year);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getPeriodType), periodType);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getPeriodValue), periodValue);

        params.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getOverdueStatus), SystemConstants.NORMAL);

        List<PropertyBillBuildingRoomCountVo> propertyBillBuildingRoomCountVos = new ArrayList<>();
        //查询符合条件的楼栋Id
        List<Long> longs = propertyBillService.queryBuildingIds(params);
        if (CollectionUtils.isEmpty(longs)) {
            Page<PropertyBillBuildingRoomCountVo> page = new Page<>(request.getPageNo(), request.getPageSize(), 0, propertyBillBuildingRoomCountVos);
            return Response.<Page<PropertyBillBuildingRoomCountVo>>ok().wrap(page);
        }

        //根据订单统计
        for (Long buildingId : longs) {
            PropertyBillBuildingRoomCountVo propertyBillBuildingRoomCountVo = new PropertyBillBuildingRoomCountVo();
            propertyBillBuildingRoomCountVo.setTotalCount(0);
            propertyBillBuildingRoomCountVo.setVillageId(villageId);
            propertyBillBuildingRoomCountVo.setBuildingId(buildingId);

            //楼栋
            VillageBuildingDto villageBuildingDto = villageBuildingService.selectCacheById(buildingId);
            if (villageBuildingDto == null) {
                propertyBillBuildingRoomCountVo.setBuildingName("楼栋");
                propertyBillBuildingRoomCountVos.add(propertyBillBuildingRoomCountVo);
            } else {
                Map<String, Object> roomParams = new HashMap<>();
                roomParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
                roomParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
                roomParams.put(LambdaUtil.getFieldName(PropertyBillDto::getBuildingId), buildingId);
                propertyBillBuildingRoomCountVo.setTotalCount(villageRoomService.queryTotal(roomParams));
                propertyBillBuildingRoomCountVo.setVillageId(villageBuildingDto.getVillageId());
                propertyBillBuildingRoomCountVo.setBuildingId(villageBuildingDto.getId());
                propertyBillBuildingRoomCountVo.setBuildingName(villageBuildingDto.getName());

                //统计楼栋逾期户数
                params.put(LambdaUtil.getFieldName(PropertyBillDto::getBuildingId), villageBuildingDto.getId());
                propertyBillBuildingRoomCountVo.setOverdueCount(propertyBillService.countRoom(params));
            }
            propertyBillBuildingRoomCountVos.add(propertyBillBuildingRoomCountVo);

        }

        Page<PropertyBillBuildingRoomCountVo> page = new Page<>(request.getPageNo(), request.getPageSize(), longs.size(), propertyBillBuildingRoomCountVos);
        return Response.<Page<PropertyBillBuildingRoomCountVo>>ok().wrap(page);
    }


    /**
     * 楼栋物业收费统计
     */
    @GetMapping("propertyBillFloorRoomInfo")
    @Operation(summary = "物业收费统计楼层信息")
    public Response<List<PropertyBillFloorRoomCountVo>> propertyBillFloorRoomInfo(
            @Parameter(description = "小区id") @RequestParam Long villageId,
            @Parameter(description = "楼栋id") @RequestParam Long buildingId,
            @Parameter(description = "楼层id") @RequestParam Long floorId,
            @Parameter(description = "收费标准id") @RequestParam(required = false) Long chargeableListId,
            @Parameter(description = "收费周期") @RequestParam(required = false) Byte periodType,
            @Parameter(description = "年份") @RequestParam(required = false) Integer year,
            @Parameter(description = "时间段对应的值,如1月对应的是1") @RequestParam(required = false) Integer periodValue
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        super.fillAuthorityData(request.getParams());

        //查询逾期订单
        Map<String, Object> propertyBillParams = new HashMap<>();
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getSysUser().getTenantId());
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), villageId);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getBuildingId), buildingId);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getFloorId), floorId);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getChargeableListId), chargeableListId);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getYear), year);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getPeriodType), periodType);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getPeriodValue), periodValue);
        propertyBillParams.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
        propertyBillParams.put(LambdaUtil.getFieldName(PropertyBillDto::getOverdueStatus), SystemConstants.NORMAL);
        int total = propertyBillService.queryTotal(propertyBillParams);
        List<PropertyBillFloorRoomCountVo> result = new ArrayList<>();

        if (total <= 0) {
            return Response.<List<PropertyBillFloorRoomCountVo>>ok().wrap(result);
        }

        List<PropertyBillDto> propertyBillDtos = propertyBillService.queryList(propertyBillParams);

        //查询对应的收费标准
        for (PropertyBillDto propertyBillDto : propertyBillDtos) {
            PropertyBillAmountVo propertyBillAmountVo = propertyBillBusiness.generatePropertyBill(propertyBillDto.getChargeableListId(), propertyBillDto.getRoomId(), propertyBillDto.getStartDate(), Boolean.FALSE);
            propertyBillDto.setPropertyBillAmount(propertyBillAmountVo);
        }

        //根据房间分组
        Map<Long, List<PropertyBillDto>> groupByParkCode = propertyBillDtos.stream().collect(Collectors.groupingBy(PropertyBillDto::getRoomId));
        for (Map.Entry<Long, List<PropertyBillDto>> longListEntry : groupByParkCode.entrySet()) {
            PropertyBillFloorRoomCountVo propertyBillFloorRoomCountVo = new PropertyBillFloorRoomCountVo();
            VillageRoomDto villageRoomDto = villageRoomService.selectCacheById(longListEntry.getKey());
            if (villageRoomDto == null) {
                continue;
            }
            List<PropertyBillDto> value = longListEntry.getValue();
            List<PropertyBillInfoVo> billInfoList = new ArrayList<>();
            String ownerName = "";
            String ownerMobile = "";
            if (CollectionUtils.isNotEmpty(value)) {
                for (PropertyBillDto propertyBillDto : value) {
                    //只需获取一次
                    if (StringUtils.isBlank(ownerName) && StringUtils.isBlank(ownerMobile)) {
                        ownerName = propertyBillDto.getOwnerName();
                        ownerMobile = propertyBillDto.getOwnerMobile();
                    }
                    billInfoList.add(getBillInfoByBillAmountVo(propertyBillDto, propertyBillDto.getPropertyBillAmount()));
                }
            }

            propertyBillFloorRoomCountVo.setVillageId(villageRoomDto.getVillageId());
            propertyBillFloorRoomCountVo.setBuildingId(villageRoomDto.getBuildingId());
            propertyBillFloorRoomCountVo.setFloorId(villageRoomDto.getFloorId());
            propertyBillFloorRoomCountVo.setRoomId(longListEntry.getKey());
            propertyBillFloorRoomCountVo.setRoomName(villageRoomDto.getName());
            propertyBillFloorRoomCountVo.setOwnerName(ownerName);
            propertyBillFloorRoomCountVo.setOwnerMobile(ownerMobile);
            propertyBillFloorRoomCountVo.setRoomArea(villageRoomDto.getRoomArea());

            propertyBillFloorRoomCountVo.setBillInfoList(billInfoList);
            result.add(propertyBillFloorRoomCountVo);
        }

        return Response.<List<PropertyBillFloorRoomCountVo>>ok().wrap(result);

    }

    public PropertyBillInfoVo getBillInfoByBillAmountVo(PropertyBillDto propertyBillDto, PropertyBillAmountVo propertyBillAmountVo) {

        PropertyBillInfoVo propertyBillInfoVo = new PropertyBillInfoVo();
        propertyBillInfoVo.setBillId(propertyBillDto.getId());
        propertyBillInfoVo.setPeriodType(propertyBillDto.getPeriodType());
        propertyBillInfoVo.setStartDate(propertyBillDto.getStartDate());
        propertyBillInfoVo.setEndDate(propertyBillDto.getEndDate());
        propertyBillInfoVo.setTotalAmount(propertyBillAmountVo.getTotalAmount());
        propertyBillInfoVo.setOverdueDate(propertyBillAmountVo.getBillCycleDateInfoVo().getOverdueDate());
        propertyBillInfoVo.setOverdueDays(propertyBillAmountVo.getBillCycleDateInfoVo().getOverdueDays());

        List<PropertyBillItemInfoVo> chargeableItemAmountVos = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(propertyBillAmountVo.getChargeableItemAmountVos())) {
            List<PropertyChargeableItemAmountVo> propertyBillItemInfoVos = propertyBillAmountVo.getChargeableItemAmountVos();

            for (PropertyChargeableItemAmountVo chargeableItemAmountVo : propertyBillItemInfoVos) {
                PropertyBillItemInfoVo propertyBillItemInfoVo = new PropertyBillItemInfoVo();
                propertyBillItemInfoVo.setChargeableItemId(chargeableItemAmountVo.getPropertyChargeableItem().getId());
                propertyBillItemInfoVo.setChargeableItemName(chargeableItemAmountVo.getPropertyChargeableItem().getName());
                propertyBillItemInfoVo.setTotalAmount(chargeableItemAmountVo.getTotalAmount());
                chargeableItemAmountVos.add(propertyBillItemInfoVo);
            }

        }

        propertyBillInfoVo.setChargeableItemAmountVos(chargeableItemAmountVos);

        return propertyBillInfoVo;
    }
}
